package com.sdyeda.readiot.fx;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.sdyeda.readiot.ReadIotApplication;
import com.sdyeda.readiot.config.Setting;
import com.sdyeda.readiot.data.SetData;
import com.sdyeda.readiot.data.SetDataService;
import com.sdyeda.readiot.data.SetSave;
import com.sdyeda.readiot.data.SetSaveService;
import com.sdyeda.readiot.iotinfo.IotData;
import com.sdyeda.readiot.iotinfo.IotInfo;
import com.sdyeda.readiot.iotinfo.JdbcIotInfo;
import com.sdyeda.readiot.iotinfo.ReadingInfo;
import com.sdyeda.readiot.scheduled.ScheduledControl;
import com.sdyeda.readiot.scheduled.ScheduledInfo.ScheduledStatus;
import com.sdyeda.readiot.tools.PoiTools;
import com.sdyeda.readiot.tools.TimeTools;

import javafx.application.Platform;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.geometry.Pos;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonBar;
import javafx.scene.control.ButtonType;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.MenuButton;
import javafx.scene.control.MenuItem;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextInputDialog;
import javafx.scene.control.Tooltip;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;
import javafx.stage.Stage;

@Component
public class MainWindowController {

	@FXML
	private TreeView<String> typeTree, comTree;
	@FXML
	private TableView<IotData> iotList;

	@FXML
	private TableColumn<IotData, Date> colreadtime, coltime;
	@FXML
	private TableColumn<IotData, Boolean> colsuccess;

	@FXML
	private ListView<String> typetotal, comtotal;

	@FXML
	private Label labstatus, labbegintime, labendtime, labusetime, labnexttime, labdiffnexttime, labtotal;

	@FXML
	private ProgressIndicator progress;

	@FXML
	private ChoiceBox<String> chostate;

	// 按钮
	@FXML
	private MenuButton btnSet;
	@FXML
	private Button btnPlay, btnStop;
	// 设置菜单
	@FXML
	private MenuItem menuSetAll, menuSetIot, menuSetSave, menuExport, menuImport, menuReload;

	@Autowired
	private ScheduledControl readtask;

	@Autowired
	private SetDataService setdata;
	@Autowired
	private SetSaveService setsave;

	// 按钮变灰标志
	private SimpleBooleanProperty taskRuning;
	private SimpleBooleanProperty taskStoped;

	private ReadingInfo readinginfo = (ReadingInfo) Setting.Get(Setting.READINGINFO);
	private String treeselected = "all"; // all; type:浸润线;com:COM1
	final String ALLIOTS = "所有传感器";

	private Image truepng = null;
	private Image falsepng = null;
	private boolean isruning = false;

	private Stage detailstage;
	private Stage diagstage;
	private DetailWindow detailwindow;

	@FXML
	public void initialize() {

		// 开始读取任务
		readtask.Start();

		// 初始化按钮
		initButtons();

		detailstage = new Stage();
		detailwindow = new DetailWindow(detailstage);

		diagstage = new Stage();
		ReadDialog readdialog = new ReadDialog(diagstage, detailstage);

		detailwindow.getController().setReaddialogcontroller(readdialog.getReaddialogcontroller());

		refushTypetree();
		refushComtree();
		refushTableView();

		try {
			truepng = new Image(getClass().getResourceAsStream("image/true.png"));
			falsepng = new Image(getClass().getResourceAsStream("image/false.png"));
		} catch (Exception e) {
		}

		chostate.getItems().addAll("全部", "成功", "失败");
		chostate.setValue("全部");

		chostate.setOnAction(new EventHandler<ActionEvent>() {
			@Override
			public void handle(ActionEvent event) {
				refushTableView();
			}
		});

		Thread clock = new Thread() {
			public void run() {
				for (;;) {
					refushStatus();

					if (isruning != readinginfo.isReading()) {
						isruning = readinginfo.isReading();
						// refushList();
					}
					try {
						sleep(1000);
					} catch (InterruptedException ex) {
					}
				}
			}
		};
		clock.start();

		// 选中树刷新工作区
		typeTree.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
			if (newValue.getValue().equals(ALLIOTS)) {
				treeselected = "all";
			} else {
				treeselected = "type:" + newValue.getValue();
			}
			refushTableView();
		});

		// 选中树刷新工作区
		comTree.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
			if (newValue.getValue().equals(ALLIOTS)) {
				treeselected = "all";
			} else {
				treeselected = "com:" + newValue.getValue();
			}
			refushTableView();
		});

		// 读取日期——格式化日期
		colreadtime.setCellFactory(c -> new TableCell<IotData, Date>() {
			@Override
			protected void updateItem(Date value, boolean empty) {

				super.updateItem(value, empty);
				if (empty || value == null) {
					setText(null);
				} else {
					setAlignment(Pos.CENTER);
					setText(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(value));
				}
			}
		});

		// 读取日期——格式化日期
		coltime.setCellFactory(c -> new TableCell<IotData, Date>() {
			@Override
			protected void updateItem(Date value, boolean empty) {

				super.updateItem(value, empty);
				if (empty || value == null) {
					setText(null);
				} else {
					setAlignment(Pos.CENTER);
					setText(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(value));
				}
			}
		});

		// 格式化--读取成功
		colsuccess.setCellFactory(c -> new TableCell<IotData, Boolean>() {

			@Override
			protected void updateItem(Boolean value, boolean empty) {

				super.updateItem(value, empty);
				if (empty || value == null) {
					setText(null);
					return;
				}

				setAlignment(Pos.CENTER);
				if (value == true) {
					this.setGraphic(new ImageView(truepng));
				} else if (getTableView().getItems().get(getIndex()).getReadtimes() != 0) { // 0次，还未读
					this.setGraphic(new ImageView(falsepng));
				}
			}

		});

		// 双击
		iotList.setOnMousePressed(new EventHandler<MouseEvent>() {
			@Override
			public void handle(MouseEvent event) {
				// super.handle(event);
				if (event.isPrimaryButtonDown() && event.getClickCount() == 2) {
					if (iotList.getSelectionModel().getSelectedItem() != null) {

						// 传递选中传感器信息到弹出窗口控制中
						detailwindow.getController().setIotdata(iotList.getSelectionModel().getSelectedItem());
						detailwindow.getController().setDiagstage(diagstage);
						detailwindow.getController().readData();
						detailstage.show();

					}
				}
			}
		});

	}

	public void refushList() {
		refushComList();
		refushTypeList();
		refushTableView();
	}

	public void refushInfo() {
		refushStatus();
	}

	// 刷新状态
	void refushStatus() {

		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);

		Platform.runLater(() -> {

			labstatus.setText(!taskRuning.get() ? "任务停止"
					: ("任务运行中" + String.format("(%s)", readinginfo.isReading() ? "正在读取..." : "读取完成")));
			if (!taskRuning.get()) { // taskStop
				return;
			}
			Date nextTime = TimeTools.NextTaskTime((String) Setting.Get(Setting.SCHEDULED_TYPE),
					(String) Setting.Get(Setting.SCHEDULED_CRON), 
					(long) Setting.Get(Setting.SCHEDULED_DELAY),
					readinginfo.getBegin());

			labbegintime.setText("开始：" + sdf.format(readinginfo.getBegin()));
			labendtime.setText("结束：" + sdf.format(readinginfo.getEnd()));
			labusetime.setText("用时：" + TimeTools.getDatePoorShort(readinginfo.getEnd(), readinginfo.getBegin()));
			labnexttime.setText("下次：" + sdf.format(nextTime));
			labdiffnexttime.setText("还剩：" + TimeTools.getDatePoorShort(nextTime, new Date()));
			labtotal.setText(String.format("成功：(%d/%d)", readinginfo.getSumSuccIots(), readinginfo.getSumIots()));

			if (readinginfo.getList() != null) {
				progress.setTooltip(new Tooltip(
						String.format("读取完成：(%d/%d)", readinginfo.getSumReadedIots(), readinginfo.getSumIots())));
				progress.setProgress((readinginfo.getSumReadedIots() == 0) ? 0.0
						: (double) readinginfo.getSumReadedIots() / (double) readinginfo.getSumIots());
			}
		});
	}

	@SuppressWarnings("unchecked")
	// 刷新按类型统计列表
	void refushTypeList() {

		String format = "%8s:  (%d/%d)";

		Map<String, Integer> typemap = readinginfo.getTypeSumIots();
		Map<String, Integer> typemapsucc = readinginfo.getTypeSumSuccIots();
		Platform.runLater(() -> {
			typetotal.getItems().clear();
			for (String key : typemap.keySet()) {
				typetotal.getItems()
						.add(String.format(format, ((Map<String, SetSave>) (Setting.Get(Setting.IOTTYPE))).get(key).getTypename(),
								typemapsucc.get(key), typemap.get(key)));
			}
		});
		typetotal.refresh();

	}

	// 刷新按串口统计列表
	void refushComList() {

		String format = "%10s:  (%d/%d)";

		Map<String, Integer> commap = readinginfo.getComSumIots();
		Map<String, Integer> commapsucc = readinginfo.getComSumSuccIots();
		Platform.runLater(() -> {
			comtotal.getItems().clear();
			for (String key : commap.keySet()) {
				comtotal.getItems().add(String.format(format, key, commapsucc.get(key), commap.get(key)));
				// System.out.print(key);
			}
		});
		comtotal.refresh();

	}

	// 刷新数据列表
	void refushTableView() {

		if (readinginfo.getList() == null) {
			return;
		}

		Platform.runLater(() -> {
			ObservableList<IotData> list = FXCollections.observableArrayList(readinginfo.getList());

			// 设置过滤
			FilteredList<IotData> filteredList = new FilteredList<>(list);

			filteredList.setPredicate(new Predicate<IotData>() {
				@Override
				public boolean test(IotData data) {
					boolean result = true;

					if (treeselected.equals(ALLIOTS)) {
						result = true;
					}
					String[] tree = treeselected.split(":");
					if (tree[0].equals("type")) {
						result = data.getTypetext().equals(tree[1]);
					}
					if (tree[0].equals("com")) {
						result = data.getCom().toUpperCase().contains(tree[1].toUpperCase());
					}
					if (chostate.getValue().equals("全部")) {
						result = result && true;
					} else if (chostate.getValue().equals("成功")) {
						result = result && data.isSuccess();
					} else {
						result = result && !data.isSuccess();
					}
					return result;
				}
			});
			iotList.setItems(filteredList);
			iotList.refresh();
		});
	}

	// 刷新类型树
	void refushTypetree() {
		TreeItem<String> root = new TreeItem<String>("所有传感器",
				new ImageView(new Image(getClass().getResourceAsStream("image/root.png"))));

		@SuppressWarnings("unchecked")
		Map<String, SetSave> typemap = (Map<String, SetSave>) Setting.Get(Setting.IOTTYPE);

		for (String key : typemap.keySet()) {
			TreeItem<String> temp = new TreeItem<String>(typemap.get(key).getTypename());
			try {
				temp.setGraphic(new ImageView(new Image(getClass().getResourceAsStream("image/type" + key + ".png"))));
			} catch (Exception e) {

			}
			root.getChildren().add(temp);
		}
		root.setExpanded(true);
		typeTree.setRoot(root);
		typeTree.refresh();

	}

	// 刷新串口树
	void refushComtree() {
		TreeItem<String> root = new TreeItem<String>("所有传感器",
				new ImageView(new Image(getClass().getResourceAsStream("image/root.png"))));

		List<String> coms = ReadingInfo.getComs(((ReadingInfo) Setting.Get(Setting.READINGINFO)).getList());

		coms.forEach(item -> {
			TreeItem<String> temp = new TreeItem<String>(item);
			try {
				temp.setGraphic(new ImageView(new Image(getClass().getResourceAsStream("image/com.png"))));
			} catch (Exception e) {
			}
			root.getChildren().add(temp);

		});

		root.setExpanded(true);
		comTree.setRoot(root);
		comTree.refresh();
	}

	void initButtons() {
		// 按钮 图片
		try {
			btnSet.setGraphic(new ImageView(new Image(getClass().getResourceAsStream("image/set.png"))));
			btnPlay.setGraphic(new ImageView(new Image(getClass().getResourceAsStream("image/play.png"))));
			btnStop.setGraphic(new ImageView(new Image(getClass().getResourceAsStream("image/stop.png"))));

			menuSetAll.setGraphic(new ImageView(new Image(getClass().getResourceAsStream("image/setall.png"))));
			menuSetIot.setGraphic(new ImageView(new Image(getClass().getResourceAsStream("image/setiot.png"))));
			menuSetSave.setGraphic(new ImageView(new Image(getClass().getResourceAsStream("image/setsave.png"))));

			menuExport.setGraphic(new ImageView(new Image(getClass().getResourceAsStream("image/export.png"))));
			menuImport.setGraphic(new ImageView(new Image(getClass().getResourceAsStream("image/import.png"))));
			menuReload.setGraphic(new ImageView(new Image(getClass().getResourceAsStream("image/reload.png"))));

			taskRuning = new SimpleBooleanProperty(readtask.getStatus().getStatus() == ScheduledStatus.running);
			taskStoped = new SimpleBooleanProperty(readtask.getStatus().getStatus() != ScheduledStatus.running);
		} catch (Exception e) {

		}
		
		btnPlay.disableProperty().bind(taskRuning);
		btnStop.disableProperty().bind(taskStoped);
		btnSet.disableProperty().bind(taskRuning);

		// 设置菜单事件
		menuSetAll.setOnAction(actionEvent -> {
			Stage stage = new Stage();
			new SetAllWindow(stage, ReadIotApplication.primaryStage);
			stage.show();
		});
		menuSetIot.setOnAction(actionEvent -> {
			Stage stage = new Stage();
			new SetIotWindow(stage, ReadIotApplication.primaryStage);
			stage.show();
		});
		menuSetSave.setOnAction(event -> {
			Stage stage = new Stage();
			new SetSaveWindow(stage, ReadIotApplication.primaryStage);
			stage.show();
		});
		menuExport.setOnAction(exent -> {

			FileChooser fc = new FileChooser();
			fc.getExtensionFilters().add(new ExtensionFilter("电子表格", "*.xls"));
			fc.setInitialFileName("export.xls");
			File file = fc.showSaveDialog(ReadIotApplication.primaryStage);

			if (file == null)
				return;

			if (PoiTools.ExportSetting(file, setdata.getAllSetData(), setsave.findAll())) {
				new Alert(AlertType.INFORMATION, "导出成功!").show();
			} else {
				new Alert(AlertType.ERROR, "导出失败!").show();
			}

		});

		menuImport.setOnAction(event -> {

			Optional<ButtonType> bt = new Alert(AlertType.CONFIRMATION, "此操作将替换原有全部设置，确定要导入吗？").showAndWait();
			if (bt.get().getButtonData() != ButtonBar.ButtonData.OK_DONE) {
				return;
			}

			FileChooser fc = new FileChooser();
			fc.getExtensionFilters().add(new ExtensionFilter("电子表格", "*.xls"));
			fc.setInitialFileName("export.xls");
			File file = fc.showOpenDialog(ReadIotApplication.primaryStage);

			Map<String, Object> ret = PoiTools.ImportSetting(file, setdata.getAllSetData());

			// 注意书写
			if ((Boolean) ret.get("success")) {
				// write date
				@SuppressWarnings("unchecked")
				List<SetData> sets = (List<SetData>) ret.get("sets");
				sets.forEach(set -> {
					setdata.save(set);
				});

				// 删除原数据
				setsave.findAll().forEach(item -> {
					setsave.delete(item);
				});
				@SuppressWarnings("unchecked")
				List<SetSave> iots = (List<SetSave>) ret.get("iots");
				iots.forEach(iot -> {
					setsave.save(iot);
				});
				new Alert(AlertType.INFORMATION, ret.get("info").toString()).show();
			} else {
				new Alert(AlertType.ERROR, ret.get("info").toString()).show();
			}

		});
		
		menuReload.setOnAction(event->{
			Optional<ButtonType> bt = new Alert(AlertType.CONFIRMATION, "确定要重新载入配置吗？").showAndWait();
			if (bt.get().getButtonData() != ButtonBar.ButtonData.OK_DONE) {
				return;
			}
			//Alert wait = new Alert(AlertType.NONE,"重新载入中,请稍候...");
			//wait.show();
			
			//设置
			Map<String,SetData> sets = setdata.getAllSetData();
			List<SetSave> setsaves = setsave.findAll();
			Setting.LoadSetting(sets,setsaves);
			
			//传感器信息
			ReadingInfo readinfo =new ReadingInfo();
			List<IotInfo> list = JdbcIotInfo.getall();
			readinfo.Init(list);
			Setting.LoadIotinfo(readinfo);
			
			//！！！解决重新读取设置无法刷运行新状态问题！！！
			readinginfo = (ReadingInfo) Setting.Get(Setting.READINGINFO);
			//wait.close();
			
			
			new Alert(AlertType.INFORMATION, "载入成功!").show();
		});

		btnPlay.setOnAction(actionEvent -> {
			readtask.Start();
			refreshButtons();
			//System.out.println(readtask.getStatus().getStatus());
			//System.out.println("开始。。。");
		});
		btnStop.setOnAction(actionEvent -> {
			TextInputDialog dialog = new TextInputDialog();
			dialog.setContentText("请输入密码");
			dialog.setHeaderText("您确认停止自动采集吗？");
			dialog.setTitle("尾矿库自动数据采集系统");
			dialog.showAndWait();
			// System.out.print(dialog.getResult());
			if (!Setting.Get(Setting.SET_PASSWORD).equals(dialog.getResult())) {
				new Alert(AlertType.ERROR, "密码错误").show();
			} else {
				// Platform.exit();
				// System.exit(0);

				readtask.Stop();
				refreshButtons();
				//System.out.println(readtask.getStatus().getStatus());
			}
		});

	}

	void refreshButtons() {
		taskRuning.setValue(readtask.getStatus().getStatus() == ScheduledStatus.running);
		taskStoped.setValue(readtask.getStatus().getStatus() != ScheduledStatus.running);
	}

}
